﻿using FlyingCircusWebIS.Controllers.Utilidades;
using FlyingCircusWebIS.Filtros;
using FlyingCircusWebIS.Models;
using FlyingCircusWebIS.ViewModels.PessoaVM;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using PagedList;

namespace FlyingCircusWebIS.Controllers
{
    [AutenticacaoFilter("A")]
    public class PessoaController : Controller
    {

        private IPessoaService pessoaService;
        private ICidadeService cidadeService;
        private IReservaService reservaService;


        public PessoaController()
        {
            pessoaService = new PessoaService();
            cidadeService = new CidadeService();
            reservaService = new ReservaService();
        }



        public ActionResult Index(int pagina = 1, string nome = "", string email = "", string cpf = "", string sexo = "")
        {
            PessoaIndexVM vm = ConstruirIndexVM(pagina, nome, email, cpf, sexo);
            return View(vm);
        }

        /* 
         * Opção: Minhas Reservas
         * Lista as reservas do usuário autenticado 
         */
        [AutenticacaoFilter]
        public ActionResult Reservas()
        {
            // Pega o usuário na sessão
            Pessoa pessoaUsuario = Session["usuario"] as Pessoa;
            int idPessoa = pessoaUsuario.IdPessoa;

            // Lista as reservas do usuário
            var reservas = reservaService.ListarReservasDaPessoa(idPessoa);

            PessoaReservasVM vm = new PessoaReservasVM();
            vm.Reservas = reservas;
            vm.TotalRegistros = reservas.Count;

            List<Tuple<int, string>> lista = new List<Tuple<int, string>>();
            foreach (var reserva in vm.Reservas)
            {
                var assentoFormatado = reservaService.ApresentaAssentoSelecionado(reserva.NumAssento, reserva.Voo.Aeronave.IdModeloAeronave);

                // associa o assento com o numero da reserva
                Tuple<int, string> tuplaIdReservaAssentoFormatado = new Tuple<int, string>(reserva.IdReserva, assentoFormatado);
                lista.Add(tuplaIdReservaAssentoFormatado);
            }
            vm.TupleIdReservaAssentoFormatado = lista;
            return View(vm);
        }

        public ActionResult Gerenciar(int id)
        {
            Pessoa registro = pessoaService.BuscarPessoaPorId(id);
            if (registro == null)
                return new HttpNotFoundResult();

            PessoaDetalhesVM vm = ConstruirDetalhesVM(id);
            return View(vm);
        }

        public ActionResult AtivarCadastroAdministracao(int id)
        {
            bool ativou = pessoaService.AtivarCadAdministracao(id);
            if (ativou)
                return RedirectToAction("Sucesso", 
                    new { titulo = "Ativação de cadastro", mensagem = "Cadastro ativado com sucesso." });
            else
                return new HttpNotFoundResult();
        }

        public ActionResult DesativarCadastroAdministracao(int id)
        {
            bool desativou = pessoaService.DesativarCadAdministracao(id);
            if (desativou)
                return RedirectToAction("Sucesso", 
                    new { titulo = "Desativação de cadastro", mensagem = "Cadastro desativado com sucesso." });
            else
                return new HttpNotFoundResult();
        }

        public ActionResult ConcederDescontoEspecial(int id)
        {
            Pessoa pessoa = pessoaService.BuscarPessoaPorId(id);
            if (pessoa == null)
                return new HttpNotFoundResult();
           
            ViewBag.Id = id;
            ViewBag.Nome = pessoa.NomeCompleto;
            return View();
        }

        [HttpPost]
        public ActionResult ConcederDescontoEspecial(int id, string valorDescontoPorc)
        {
            Decimal desconto = (Decimal.Parse(valorDescontoPorc) / 100);
            pessoaService.AtribuirDescontoParaPessoa(id, desconto);

            return RedirectToAction("Sucesso", 
                new { titulo = "Desconto", mensagem = "Desconto atribuido com sucesso." });
        }

        public ActionResult RemoverDescontoEspecial(int id)
        {
            bool removeu = pessoaService.RemoverDescontoEspecial(id);
            if (removeu)
                return RedirectToAction("Sucesso", 
                    new { titulo = "Desconto", mensagem = "Desconto removido com sucesso." });
            else
                return new HttpNotFoundResult();
        }

        public ActionResult CancelarRecebimentoMarketing(int id)
        {
            bool cancelou = pessoaService.CancelarRecimentoMarketing(id);
            if (cancelou)
                return RedirectToAction("Sucesso", 
                    new { titulo = "Marketing", mensagem = "Cancelamento de recimento de marketing efetuado com sucesso." });
            else
                return new HttpNotFoundResult();
        }

        public ActionResult AtivarRecebimentoMarketing(int id)
        {
            bool ativou = pessoaService.AtivarRecebimentoMarketing(id);
            if (ativou)
                return RedirectToAction("Sucesso", 
                    new { titulo = "Marketing", mensagem = "Ativação de recimento de marketing efetuada com sucesso." });
            else
                return new HttpNotFoundResult();
        }


        public ActionResult ConcederDireitoAdministrativo(int id)
        {
            bool concedeu = pessoaService.ConcederDireitoAdministrativo(id);
            if (concedeu)
                return RedirectToAction("Sucesso", 
                    new { titulo = "Administração", mensagem = "Concessão de direito administrativo realizada com sucesso." });
            else
                return new HttpNotFoundResult();
        }


        public ActionResult RevogarDireitoAdministrativo(int id)
        {
            bool revogou = pessoaService.RevogarDireitoAdministrativo(id);
            if (revogou)
                return RedirectToAction("Sucesso",
                    new { titulo = "Administração", mensagem = "Revogação de direito administrativo realizada com sucesso." });
            else
                return new HttpNotFoundResult();
        }

        public ActionResult Sucesso(string titulo, string mensagem)
        {
            ViewBag.Titulo = titulo;
            ViewBag.Mensagem = mensagem;
            return View();
        }


        // -----------------------------------------------------------------------------------------
        // As demais actions abaixo podem ser acessadas por um usuário não autenticado
        // -----------------------------------------------------------------------------------------


        [PermitirAnonimos]
        public ActionResult Cadastrar()
        {
            PessoaCadastrarVM vm = ConstruirCadastrarVM();
            return View(vm);
        }

        [PermitirAnonimos]
        [HttpPost]
        public ActionResult Cadastrar(PessoaCadastrarVM vm)
        {
            if (ModelState.IsValid)
            {
                Endereco endereco = ConverterCadVMParaEndereco(vm);
                Pessoa pessoa = ConverterCadVMParaPessoa(vm);
                List<Telefone> telefones = ConverterCadVMParaTelefones(vm);

                var erros = pessoaService.ValidaAdicionarPessoa(pessoa);
                if (erros.Count == 0)
                {
                    pessoaService.Adicionar(pessoa, endereco, telefones);

                    return RedirectToAction("CadastrarAtivacao", new { email = pessoa.Email });
                }
                else
                {
                    ModelState.AddModelErrors(erros);
                }
            
            }

            PopularItensCadastrarVM(vm);
            return View(vm);
        }

        [PermitirAnonimos]
        public ActionResult CadastrarAtivacao(string email)
        {
            ViewBag.Email = email;
            return View();
        }

        [PermitirAnonimos]
        public ActionResult AtivarCad(string cod = null)
        {
            if (cod != null)
            { 
                // tenta ativar
                bool ativou = pessoaService.AtivarCad(cod);
                if (ativou)
                {
                    ViewBag.Mensagem = "Registro ativado com sucesso! Realize a autenticação para continuar comprando.";
                    return View();
                }
            }

            ViewBag.Mensagem = "Não é possível ativar o registro solicitado. Contate a área de suporte.";
            return View();
        }


        [PermitirAnonimos]
        public JsonResult BuscarItensCidades(string uf)
        {
            var itens = cidadeService.ListarItensCidadesPorUF(uf);
            return Json(itens, JsonRequestBehavior.AllowGet);
        }



        // -----------------------------------------------------------------------------------------
        // Métodos auxiliares 
        // -----------------------------------------------------------------------------------------


        private List<Telefone> ConverterCadVMParaTelefones(PessoaCadastrarVM vm)
        {
            List<Telefone> telefones = new List<Telefone>();

            string numeroTelefoneUm = vm.telefoneUm;
            if (!String.IsNullOrEmpty(numeroTelefoneUm))
            {
                Telefone telefoneUm = new Telefone();
                telefoneUm.TelefoneNumero = RemoverFormatacaoTelefone(numeroTelefoneUm);
                telefones.Add(telefoneUm);
            }
                
            string numeroTelefoneDois = vm.telefoneDois;
            if (!String.IsNullOrEmpty(numeroTelefoneDois))
            {
                Telefone telefoneDois = new Telefone();
                telefoneDois.TelefoneNumero = RemoverFormatacaoTelefone(numeroTelefoneDois);
                telefones.Add(telefoneDois);
            }

            return telefones;
        }

        private string RemoverFormatacaoTelefone(string telefoneFormatado)
        {
            string telefoneApenasNumeros = telefoneFormatado.Replace("(", "").Replace(")", "").Replace(" ", "");
            return telefoneApenasNumeros;
        }

        private Endereco ConverterCadVMParaEndereco(PessoaCadastrarVM vm)
        {
            Endereco endereco = new Endereco();
            endereco.IdCidade = vm.IdCidade;
            endereco.Logradouro = vm.Logradouro;
            endereco.Numero = vm.Numero;
            endereco.Complemento = vm.Complemento;
            endereco.Cep = RemoverFormatacaoCEP(vm.CEP);
            return endereco;
        }

        private string RemoverFormatacaoCEP(string cepFormatado)
        {
            string cepApenasNumeros = cepFormatado.Replace("-", "");
            return cepApenasNumeros;
        }

        private Pessoa ConverterCadVMParaPessoa(PessoaCadastrarVM vm)
        {
            Pessoa pessoa = new Pessoa();
            pessoa.CPF = RemoverFormatacaoCPF(vm.CPF);
            pessoa.DataNascimento = DateTime.Parse(vm.DataNascimento);
            pessoa.Email = vm.Email;
            pessoa.NomeCompleto = vm.Nome;
            pessoa.Ocupacao = vm.Ocupacao;
            if (!String.IsNullOrEmpty(vm.Renda))
                pessoa.Renda = Decimal.Parse(vm.Renda, System.Globalization.CultureInfo.InvariantCulture);
            pessoa.SenhaSistema = vm.Senha;
            pessoa.Sexo = vm.Sexo;
            pessoa.UsuarioSistema = vm.Usuario;
            return pessoa;
        }

        private string RemoverFormatacaoCPF(string cpfFormatado)
        {
            string cpfApenasNumeros = cpfFormatado.Replace(".", "").Replace("-", "");
            return cpfApenasNumeros;
        }

        private PessoaCadastrarVM ConstruirCadastrarVM()
        {
            PessoaCadastrarVM vm = new PessoaCadastrarVM();
            vm.Sexo = "M";
            vm.ReceberMarketing = true;
            PopularItensCadastrarVM(vm);
            return vm;
        }

        private void PopularItensCadastrarVM(PessoaCadastrarVM vm)
        { 
            vm.ItensUF = cidadeService.ListarItensUF();
            string uf = vm.UF;
            if (!String.IsNullOrEmpty(uf))
                vm.ItensCidades = cidadeService.ListarItensCidadesPorUF(vm.UF);
            else
                vm.ItensCidades = cidadeService.ListarItensCidadesParaNovo();
        }

        private PessoaDetalhesVM ConstruirDetalhesVM(int id)
        {
            // Obtem os dados necessários
            int idPessoa = id;
            Pessoa pessoa = pessoaService.BuscarPessoaPorId(idPessoa);
            int idEndereco = pessoa.IdEndereco;
            Endereco endereco = pessoaService.BuscarEnderecoPorId(idEndereco);
            int idCidade = endereco.IdCidade;
            Cidade cidade = cidadeService.BuscarPorId(idCidade);
            List<Telefone> telefonesEntidades = pessoaService.ListarTelefonesPorIdPessoa(idPessoa);

            // Realiza a conversão
            PessoaDetalhesVM vm = new PessoaDetalhesVM();
            vm.NomeCompleto = pessoa.NomeCompleto;
            vm.Email = pessoa.Email;
            vm.Sexo = pessoa.Sexo.Equals("M") ? "Masculino" : "Feminino";
            DateTime dataNascimento = pessoa.DataNascimento;
            if (dataNascimento != null)
            {
                vm.DataNascimento = dataNascimento.ToShortDateString();
                vm.Idade = (DateTime.Now.Year - dataNascimento.Year).ToString();
            }
            string ocupacao = pessoa.Ocupacao;
            vm.Ocupacao = !String.IsNullOrEmpty(ocupacao) ? ocupacao : "Não informada";
            string renda = pessoa.Renda.Value.ToString("c");
            vm.Renda = !String.IsNullOrEmpty(renda) ? renda : "Não informada";
            vm.CPF = pessoa.CPF;

            if (telefonesEntidades != null || telefonesEntidades.Count != 0)
            {
                vm.Telefones = new List<string>();
                foreach (var telefoneEntidade in telefonesEntidades)
                {
                    string telefoneFormatado = FormatarNumeroTelefone(telefoneEntidade.TelefoneNumero);
                    vm.Telefones.Add(telefoneFormatado);
                }
            }

            vm.Logradouro = endereco.Logradouro;
            vm.NumeroEndereco = endereco.Numero;
            string complementoDoEndereco = endereco.Complemento;
            vm.ComplementoEndereco = !String.IsNullOrEmpty(complementoDoEndereco) ? complementoDoEndereco : "Não informado";
            vm.NomeCidade = cidade.NomeCidade;
            vm.UF = cidade.UF;
            vm.Pais = cidade.Pais;
            vm.CEP = endereco.Cep;

            vm.IdPessoa = idPessoa.ToString();
            vm.Usuario = pessoa.UsuarioSistema;
            vm.DescontoEspecial = pessoa.DescontoEspecial.Equals("S");

            string porcDescontoEspecialString;
            if (pessoa.PorcDescontoEspecial != null)
                porcDescontoEspecialString = pessoa.PorcDescontoEspecial.Value.ToString("P");
            else
                porcDescontoEspecialString = "Sem desconto";
            vm.PorcDescontoEspecial = porcDescontoEspecialString;

            vm.RecebeMarketing = pessoa.RecebeInfoMarketing.Equals("S");
            vm.NivelAdministrador = pessoa.NivelPessoa.Equals("A");
            vm.CadastroAtivo = pessoa.CadastroAtivo.Equals("S");

            return vm;
        }

        private string FormatarNumeroTelefone(string telefoneApenasNumero)
        { 
            string telefoneFormatado = telefoneApenasNumero.Insert(0, "(").Insert(3, ")").Insert(4, " ");
            return telefoneFormatado;
        }


        private PessoaIndexVM ConstruirIndexVM(int pagina, string nome, string email, string cpf, string sexo)
        {
            // Usa o componente PagedList para paginar os resultados para a página solicitada
            var registros = pessoaService.ListarPessoasFiltro(nome, email, cpf, sexo).ToPagedList(pagina, 15);
            
            PessoaIndexVM vm = new PessoaIndexVM();
            vm.Registros = registros;
            vm.TotalRegistros = registros.Count;
            vm.ItensSexo = ListarItensSexo();
            vm.Nome = nome;
            vm.Email = email;
            vm.CPF = cpf;
            vm.Sexo = sexo;
            return vm;
        }

        private List<SelectListItem> ListarItensSexo()
        {
            List<SelectListItem> itensSexo = new List<SelectListItem>();
            itensSexo.Add(new SelectListItem() { Text = "<Todos>", Value = "" });
            itensSexo.Add(new SelectListItem() { Text = "Masculino", Value = "M" });
            itensSexo.Add(new SelectListItem() { Text = "Feminino", Value = "F" });
            return itensSexo;
        }

    }
}
